package com.zyx.xxl.executor.utils;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.zyx.xxl.executor.domain.XxlJobStaticConfig;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

/**
 * @author Yaxi.Zhang
 * @since 2022/6/13 16:52
 */
@Component
public class XxlJobUtil {

    private static String cookie = "";

    private static RestTemplate restTemplate;

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        XxlJobUtil.restTemplate = restTemplate;
    }

    /**
     * 新增/编辑任务
     */
    public static JSONObject addJob(MultiValueMap requestInfo) throws HttpException, IOException {
        // 1.拼接url
        String path = "/jobinfo/add";
        String targetUrl = XxlJobStaticConfig.adminAddresses + path;

        // 2.获得cookie
        String cookie = XxlJobUtil.login();

        // 2.封装请求格式
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Cookie", cookie);
        HttpEntity httpEntity = new HttpEntity(requestInfo, headers);

        // 4.发送请求
        ResponseEntity<String> exchange = restTemplate.exchange(targetUrl, org.springframework.http.HttpMethod.POST, httpEntity, String.class);

        // 5.返回结果集 "code": 200,"msg": null, "content": "任务id"
        String body = exchange.getBody();
        JSONObject result = JSONObject.parseObject(body);
        return result;
    }

    public static JSONObject updateJob(String url, MultiValueMap requestInfo) throws HttpException, IOException {
        String path = "/jobinfo/update";
        String targetUrl = url + path;
        HttpClient httpClient = new HttpClient();
        PostMethod post = new PostMethod(targetUrl);
        RequestEntity requestEntity = new StringRequestEntity(requestInfo.toString(), MediaType.APPLICATION_FORM_URLENCODED_VALUE, "utf-8");
        post.setRequestEntity(requestEntity);
        httpClient.executeMethod(post);
        JSONObject result = new JSONObject();
        result = getJsonObject(post, result);
        return result;
    }

    /**
     * 删除任务
     *
     * @param id 任务id
     * @return
     * @throws HttpException
     * @throws IOException
     */
    public static JSONObject deleteJob(int id) throws HttpException, IOException {
        // TODO: 请求无返回值，任务删除成功。
        // 1.拼接URL
        String path = "/jobinfo/remove";
        String url = XxlJobStaticConfig.adminAddresses;
        String targetUrl = url + path;

        // 2.获得cookie
        String cookie = XxlJobUtil.login();

        // 3.封装请求参数
        MultiValueMap requestInfo = new LinkedMultiValueMap();
        requestInfo.add("id", id);

        // 4.封装请求格式
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Cookie", cookie);
        HttpEntity httpEntity = new HttpEntity(requestInfo, headers);

        // 5.发送请求
        ResponseEntity<String> exchange = restTemplate.exchange(targetUrl, org.springframework.http.HttpMethod.POST, httpEntity, String.class);

        // 6.返回结果集     "code": 200,"msg": null, "content": null
        String body = exchange.getBody();
        JSONObject result = JSONObject.parseObject(body);
        return result;
    }

    /**
     * 开始任务
     */
    public static JSONObject startJob(int id) throws HttpException, IOException {
        // 1.拼接URL
        String path = "/jobinfo/start";
        String url = XxlJobStaticConfig.adminAddresses;
        String targetUrl = url + path;

        // 2.获得cookie
        String cookie = XxlJobUtil.login();

        // 3.封装请求参数
        MultiValueMap requestInfo = new LinkedMultiValueMap();
        requestInfo.add("id", id);

        //4.封装请求格式
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Cookie", cookie);
        HttpEntity httpEntity = new HttpEntity(requestInfo, headers);

        // 5.发送请求
        ResponseEntity<String> exchange = restTemplate.exchange(targetUrl, org.springframework.http.HttpMethod.POST, httpEntity, String.class);

        // 6.返回结果集     "code": 200, "msg": null, "content": null
        String body = exchange.getBody();
        JSONObject result = JSONObject.parseObject(body);
        return result;
    }

    /**
     * 停止任务
     */
    public static JSONObject stopJob(int id) throws HttpException, IOException {
        // 1.拼接URL
        String path = "/jobinfo/stop";
        String url = XxlJobStaticConfig.adminAddresses;
        String targetUrl = url + path;

        // 2.获得cookie
        String cookie = XxlJobUtil.login();

        // 3.封装请求参数
        MultiValueMap requestInfo = new LinkedMultiValueMap();
        requestInfo.add("id", id);

        // 4.封装请求格式
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Cookie", cookie);
        HttpEntity httpEntity = new HttpEntity(requestInfo, headers);

        // 5.发送请求
        ResponseEntity<String> exchange = restTemplate.exchange(targetUrl, org.springframework.http.HttpMethod.POST, httpEntity, String.class);

        // 6.返回结果集     "code": 200,"msg": null, "content": null
        String body = exchange.getBody();
        JSONObject result = JSONObject.parseObject(body);
        return result;
    }

    /**
     * 根据xxl-appname获取对应id
     */
    public static JSONObject getAppNameIdByAppname(String url, String appnameParam) throws HttpException, IOException {
        String path = "/jobgroup/getAppNameIdByAppname?appnameParam=" + appnameParam;
        return doGet(url, path);
    }

    public static JSONObject doGet(String url, String path) throws HttpException, IOException {
        String targetUrl = url + path;
        HttpClient httpClient = new HttpClient();
        HttpMethod get = new GetMethod(targetUrl);
        get.setRequestHeader("cookie", cookie);
        httpClient.executeMethod(get);
        JSONObject result = new JSONObject();
        result = getJsonObject(get, result);
        return result;
    }

    private static JSONObject getJsonObject(HttpMethod get, JSONObject result) throws IOException {
        InputStream inputStream = get.getResponseBodyAsStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer stringBuffer = new StringBuffer();
        String str = "";
        while ((str = br.readLine()) != null) {
            stringBuffer.append(str);
        }
        if (get.getStatusCode() == 200) {
            // 使用此方式会出现
            // Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.
            // 异常
            // String responseBodyAsString = get.getResponseBodyAsString();
            // result = JSONObject.parseObject(responseBodyAsString);*/
            result = JSONObject.parseObject(stringBuffer.toString());
        } else {
            try {
                // result = JSONObject.parseObject(get.getResponseBodyAsString());
                result = JSONObject.parseObject(stringBuffer.toString());
            } catch (Exception e) {
                result.put("error", stringBuffer.toString());
            }
        }
        return result;
    }

    /**
     * 登录xxl-job
     *
     * @return 返回cookie
     */
    public static String login() {
        // 1.拼接URL
        String path = "/login";
        String url = XxlJobStaticConfig.adminAddresses;
        String targetUrl = url + path;

        // 2.封装参数
        MultiValueMap<String, Object> requestInfo = new LinkedMultiValueMap<>();
        requestInfo.add("userName", XxlJobStaticConfig.userName);
        requestInfo.add("password", XxlJobStaticConfig.password);
        requestInfo.add("ifRemember", XxlJobStaticConfig.ifRemember);

        // 3.封装请求
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity httpEntity = new HttpEntity(requestInfo, headers);

        // 4.发送请求，返回Cookie
        ResponseEntity<String> exchange = restTemplate.exchange(targetUrl,
                org.springframework.http.HttpMethod.POST, httpEntity, String.class);
        List<String> list = exchange.getHeaders().get("Set-Cookie");
        return CollUtil.isEmpty(list)? null: list.get(0);
    }
}
